#!/usr/bin/env python
# encoding: utf-8
"""
Builds kml from latest LA bucket brigade data.  Improves on kml offered
"""

import sys
import os
import httplib
import json
from xml.sax import saxutils
from boto.s3 import Connection
from optparse import OptionParser
from datetime import datetime

BASE_URL = "www.oilspill.labucketbrigade.org"
CATEGORIES_URL = "/api?task=categories&by=all&resp=json"
INCIDENTS_URL = "/api?task=incidents&by=catid&resp=json&limit=100"
MEDIA_URL = "http://www.oilspill.labucketbrigade.org/media/uploads/"
S3_BUCKET = "https://s3.amazonaws.com/marinemap-gulfspill"

help_message = '''
The help message goes here.
'''

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def get_categories():
    conn = httplib.HTTPConnection(BASE_URL)
    content = []
    req = conn.request("GET", CATEGORIES_URL)
    r1 = conn.getresponse()
    categories = []
    if r1.status is 200:
        result = json.loads(r1.read())
        if result.get('error').get('code') == '0':
            cat_result = result.get('payload').get('categories')
    else:
        print "epic fail fetching records"
        return     
    for record in cat_result:
        categories.append(record.get('category'))
    return categories

def get_incidents_by_cat(category):
    conn = httplib.HTTPConnection(BASE_URL)
    content = []
    req = conn.request("GET", INCIDENTS_URL+'&id='+category.get('id'))
    r1 = conn.getresponse()
    if r1.status is 200:
        result = json.loads(r1.read())
        if result.get('error').get('code') == '0':
            incidents = result.get('payload').get('incidents')
    else:
        print "epic fail fetching records"
        return       
    return incidents

def create_kml(categories, begin, end):
    print begin, end
    cat_links = create_network_links(categories)               
    kml = """<?xml version="1.0" encoding="UTF-8"?>
        <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
            <Document>
            <name>Louisiana Bucket Brigade Crisis Map</name>
            <LookAt>
        		<gx:TimeSpan>
        			<begin>%s</begin>
        			<end>%s</end>
        		</gx:TimeSpan>
        		<longitude>-86.5087528807807</longitude>
        		<latitude>28.76558605246543</latitude>
        		<altitude>0</altitude>
        		<range>1420274.687072554</range>
        		<tilt>0</tilt>
        		<heading>1.692316236596836</heading>
        		<altitudeMode>relativeToGround</altitudeMode>
        		<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
        	</LookAt>
        	<Style id="sh_oildrop0">
        		<IconStyle>
        		    <color>ff0080ff</color>
        			<scale>1.2</scale>
        			<Icon>
        				<href>http://maps.google.com/mapfiles/kml/shapes/target.png</href>
        			</Icon>
        		</IconStyle>
        		<LabelStyle>
        			<color>00ffffff</color>
        		</LabelStyle>
        		<BalloonStyle>
                      <!-- a background color for the balloon -->
                      <text>$[description]</text>
                </BalloonStyle>
        	</Style>
        	<StyleMap id="msn_oildrop0">
        		<Pair>
        			<key>normal</key>
        			<styleUrl>#sn_oildrop</styleUrl>
        		</Pair>
        		<Pair>
        			<key>highlight</key>
        			<styleUrl>#sh_oildrop0</styleUrl>
        		</Pair>
        	</StyleMap>
        	<Style id="sn_oildrop">
        		<IconStyle>
        		    <color>ff0080ff</color>
        			<Icon>
        				<href>http://maps.google.com/mapfiles/kml/shapes/target.png</href>
        			</Icon>
        		</IconStyle>
        		<BalloonStyle>
                      <!-- a background color for the balloon -->
                      <text>$[description]</text>
                </BalloonStyle>
        		<LabelStyle>
        			<color>00ffffff</color>
        		</LabelStyle>
        	</Style>
                %s
            </Document>
        </kml>
    """ % (begin.strftime("%Y-%m-%dT%H:%M:%SZ"), end.strftime("%Y-%m-%dT%H:%M:%SZ"), cat_links)    
    return kml

def create_cat_kml(placemarks):
    '''
    Create kml for a given category
    '''     
    kml = """<?xml version="1.0" encoding="UTF-8"?>
        <kml xmlns="http://www.opengis.net/kml/2.2">
            <Document>
        	<Style id="sh_oildrop0">
        		<IconStyle>
        		    <color>ff0080ff</color>
        			<scale>1.2</scale>
        			<Icon>
        				<href>http://maps.google.com/mapfiles/kml/shapes/target.png</href>
        			</Icon>
        		</IconStyle>
        		<LabelStyle>
        			<color>00ffffff</color>
        		</LabelStyle>
        		<BalloonStyle>
                      <!-- a background color for the balloon -->
                      <text>$[description]</text>
                </BalloonStyle>
        	</Style>
        	<StyleMap id="msn_oildrop0">
        		<Pair>
        			<key>normal</key>
        			<styleUrl>#sn_oildrop</styleUrl>
        		</Pair>
        		<Pair>
        			<key>highlight</key>
        			<styleUrl>#sh_oildrop0</styleUrl>
        		</Pair>
        	</StyleMap>
        	<Style id="sn_oildrop">
        		<IconStyle>
        		    <color>ff0080ff</color>
        			<Icon>
        				<href>http://maps.google.com/mapfiles/kml/shapes/target.png</href>
        			</Icon>
        		</IconStyle>
        		<BalloonStyle>
                      <!-- a background color for the balloon -->
                      <text>$[description]</text>
                </BalloonStyle>
        		<LabelStyle>
        			<color>00ffffff</color>
        		</LabelStyle>
        	</Style>
                %s
            </Document>
        </kml>
    """ % (placemarks)    
    return kml    

def create_network_links(categories):
    links = []    
    for cat in categories:        
        #Create a network link that points at our new category kml
        links.append("""
			<NetworkLink>
                <name>%s</name>
				<visibility>1</visibility>
				<Link>
					<href>%s/la_brigade/cat_%s.kmz</href>
				</Link>
			</NetworkLink>
        """ % (cat['title'], S3_BUCKET, cat['id']))
    return "\n".join(links)

def create_placemarks(incidents):
    placemarks = []
    for i in incidents:
        time_list = i['incident']['incidentdate'].split(' ')
        timestamp = time_list[0]+'T'+time_list[1]+'Z'
        placemarks.append("""
            <Placemark>
              <styleUrl>#msn_oildrop0</styleUrl>
              <name>%s</name>
              <description>%s</description>
              <visibility>1</visibility>
              <Point>
                <coordinates>%s,%s,0</coordinates>
              </Point>
              <TimeStamp>
                <when>%s</when>
              </TimeStamp>
            </Placemark>
        """ % (i['incident']['incidenttitle'], create_description(i),i['incident']['locationlongitude'], 
            i['incident']['locationlatitude'], timestamp))
    return "\n".join(placemarks)

def create_description(r):
    verified = r['incident']['incidentverified']
    if verified == '0':
        verified = 'No'
    else:
        verified = 'Yes'
    d = """
        <table>
            <tr>
                <td width="300">
                    <h3>%s</h3>
                    <p><b>Description </b> %s</p>              
                    <p><b>Verified:</b> %s</p>
                    <p><b>Date:</b> %s</p>
    """ % (r['incident']['incidenttitle'],r['incident']['incidentdescription'],
        verified, r['incident']['incidentdate'])

    if 'media' in r and len(r['media']) is not 0:
        for media_rec in r['media']:
            if media_rec['mediatype'] == '1':   #Image
                d = d + '<p><img src="%s"></p>' % (MEDIA_URL+media_rec['medialink'])
            elif media_rec['mediatype'] == '2' or media_rec['mediatype'] == '4': #Link
                d = d + '<p><a target="_blank" href="%s">Media Link</a></p>' % (media_rec['medialink'])
    d = d + """            <a href="http://oilspill.labucketbrigade.org/">http://oilspill.labucketbrigade.org/</a>
                    </td>
                    </tr>
                </table>
    """
            
    return """<![CDATA[%s]]>""" % (d, )

def percent_cb(complete, total):
    '''
    Simple progress indicator for transferring files
    '''
    sys.stdout.write('.')
    sys.stdout.flush()   

def push_str_to_s3(the_str, bucket_name, key_name, acl_str):
    #Push kml up to S3.  Requires boto connection config has been setup on the system
    #If a better way of safely providing the aws keys is available, feel free to chance
    from kml import create_kmz
    kmz = create_kmz(the_str)
    connection = Connection()
    bucket = connection.get_bucket(bucket_name)
    from boto.s3.key import Key
    k = Key(bucket)
    k.key = key_name
    k.set_contents_from_string(kmz, cb=percent_cb, num_cb=10)
    k.set_acl(acl_str)
    print "\nFile can be access from http://%s/%s" % (".".join((bucket.name, connection.server_name())), k.key)
    
    
def main(argv=None):
    usage = "usage: %prog [--upload]"
    parser = OptionParser(usage)
    parser.add_option("-u", "--upload",
                      action="store_true", dest="upload", default=False,
                      help="upload output to s3 as marinemap-gulfspill/la_brigade.kml. Otherwise output will be directed to stdout")

    (options, args) = parser.parse_args()

    #Get all the incident categories
    categories = get_categories()
    
    begin = None
    end = None
    #Create category specific kml files
    for cat in categories:        
        incidents = get_incidents_by_cat(cat)
        for i in incidents:
            time_list = i['incident']['incidentdate'].split(' ')
            timestamp = time_list[0]+'T'+time_list[1]+'Z'
            dt = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ")
            if begin is None or dt < begin:
                begin = dt
            if end is None or dt > end:
                end = dt
        #Skip a category if there are no reports for it
        # if len(incidents) == 0:
        #     continue            
        #Generate placemarks for category incidents
        placemarks = create_placemarks(incidents)        
        
        #Create placemark kml for current category
        cat_kml = create_cat_kml(placemarks)
        #Boto requires ascii and sometimes unicode characters show up
        cat_kml = cat_kml.encode('ascii','ignore')        
        #Generate filename for given category
        cat_kml_key = "la_brigade/cat_"+cat['id']+".kmz"
        #Push to S3 or print out
        if options.upload:
            push_str_to_s3(cat_kml, 'marinemap-gulfspill',cat_kml_key,'public-read')
        else:
            print cat_kml
    #Create the top-level kml file
    kml = create_kml(categories, begin, end)
    #Boto requires ascii
    kml = kml.encode('ascii','ignore')
    #Push or print the top-level kml file
    if options.upload:
        push_str_to_s3(kml, 'marinemap-gulfspill','la_brigade/la_brigade.kmz','public-read')
    else:
        print kml        

if __name__ == "__main__":
    sys.exit(main())
